from emi.util import NumUtils, utils


class AssertUtils:

    @staticmethod
    def assert_equal(ob1, ob2):
        if ob1 is None:
            assert ob2 is None
        if isinstance(ob1,float):
            assert NumUtils.is_equal(ob1,ob2)
        assert ob1 == ob2

    @staticmethod
    def assert_euqal_float(price1, price2, p: float, msg: str = ""):
        diff = abs(price1 - price2)
        if diff > p:
            print(f"assert fail:f1({price1})f2({price2}), abs(f1-f2) = {diff} > {p}, {msg}")
            assert False

    @staticmethod
    def assert_equal_bars(bars, bars2,
                          check_datetime_is_same_day=False,
                          volum_diff=1, index=0, P=0.0011):
        from emi.bar.data import BarData

        if isinstance(bars, list) and isinstance(bars2, list):
            assert len(bars) == len(bars2)
            for i in range(0, len(bars)):
                AssertUtils.assert_equal_bars(bars[i], bars2[i],
                                              check_datetime_is_same_day=check_datetime_is_same_day,
                                              volum_diff=volum_diff,
                                              index=i,
                                              P=P
                                              )
        else:

            bar1: BarData = bars
            bar2: BarData = bars2
            if bar1 is None and bars2 is None:
                return True;
            ## 精度值保留三位小数
            # print(f"{bar1}")
            # print(f"{bar2}")
            if check_datetime_is_same_day:
                assert utils.is_same_day(bar1.datetime, bar2.datetime)
            else:
                assert abs(bar1.datetime.timestamp() - bar2.datetime.timestamp()) <= 60
            if abs(bar1.volume - bar2.volume) >= volum_diff:
                print(
                    f"index ={index},bar.volume({bar1.volume}) != bar2.volume({bar2.volume}, bar1:{bar1},bar2:{bar2})")
                assert False
            # assert abs(bar1.close_price -bar2.close_price) <= P
            # assert abs(bar1.open_price -bar2.open_price) <= P
            # assert abs(bar1.high_price -bar2.high_price) <= P
            # assert abs(bar1.low_price -bar2.low_price) <= P
            msg = f"\nindex={index},bar1={bar1},bar2={bar2}"

            from emi.barx.data import BarX
            ## 开盘价跟收盘价要一致
            AssertUtils.assert_euqal_float(bar1.close, bar2.close, P, msg)
            AssertUtils.assert_euqal_float(bar1.open, bar2.open, P, msg)
            if isinstance(bar1,BarData):
                AssertUtils.assert_euqal_float(bar1.price_adjust, bar2.price_adjust, P, msg)
            elif isinstance(bar1,BarX):
                assert bar1.dimen_value == bar2.dimen_value


            ###
            AssertUtils.assert_euqal_float(bar1.high, bar2.high, P, msg)
            AssertUtils.assert_euqal_float(bar1.low, bar2.low, P, msg)
            AssertUtils.assert_euqal_float(bar1.amount, bar2.amount, P, msg)
            AssertUtils.assert_euqal_float(bar1.pre_close, bar2.pre_close, P, msg)

            assert bar1.interval == bar2.interval